package cn.org.dian.easycommunicate;

import java.io.File;
import java.io.IOException;

import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.AsyncTask;
import cn.org.dian.easycommunicate.util.Constants;
import cn.org.dian.easycommunicate.util.NetworkTrafficStats;
import cn.org.dian.easycommunicate.util.OnlineTTS;
import cn.org.dian.easycommunicate.util.Utilities;

import com.google.api.translate.Language;

/**
 * Base class for any Activity who wants to use TTS service
 * Call {@link #speakTTSEngine(String, int)} for speak
 * @author LiuGen
 * @see #speakTTSEngine(String, int)
 */
public class TTSActivity extends Activity {

    
    private static final String TAG = "TTSActivity";

    
    private MediaPlayer mediaPlayer = null;
    


    
    protected void asyncSpeak(Language language, String speakText) {
        new AsyncSpeakTask().execute(language, speakText);
    }
    
    
    /**
     * 
     * @param language
     * @param speakText
     * @return true if success
     */
    protected boolean speak(Language language, String speakText) {
        
        // check cache 
        File audioCacheFile = OnlineTTS.getCachedAudioFile(language, speakText);    
        if (null != audioCacheFile) {
            // if cache exists
            return playFromAudioFile(audioCacheFile);
        } else {
            // cache does not exist, check network and user pref for using online TTS service
            
            // get user pref whether uses online TTS
            // boolean useNetworkForTTS = true; // alway use network TTS
            //Utilities.getSharedPreferences().getBoolean("use_network_for_tts", false);
            
            // TODO prompt user open network
        	
        	// request web for voice
        	       	
            if (Utilities.checkNetworkUsability()) {
                                
                // check cache file name, if too long, won't cache, just stream play
                String legalFileName = Utilities.convertToLegalName(speakText);
                
                if (Utilities.checkSDCardUsability() && legalFileName.length() <= Constants.FILE_NAME_LENGTH_MAX) {
                    // SD card is available and file name is shorter than 256,
                    // request web and save to cache file.
                    // audioCacheFile is null before this call
                    audioCacheFile = OnlineTTS.requestWebAndSaveToFile(language, speakText);
                    if (null != audioCacheFile && audioCacheFile.exists()) {
                        return playFromAudioFile(audioCacheFile);
                    } else {
                        return false;
                    }
                } else {
                    // SD card not available, stream play from web
                    return streamSpeakOnline(language, speakText);
                }
            } else {
                // no network
            	// Utilities.showShortToast(getContextActivity(), R.string.network_error);
                return false;
            }
        }
    }
    
    private boolean streamSpeakOnline(Language language, String speakText) {
        
        String URL = OnlineTTS.getURL(language, speakText);
        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setDataSource(URL);
            NetworkTrafficStats.beginTrafficStats(true);
            mediaPlayer.prepare();
        } catch (IllegalArgumentException e1) {
            NetworkTrafficStats.endTrafficStats(true);
            e1.printStackTrace();
            return false;
        } catch (IllegalStateException e1) {
            NetworkTrafficStats.endTrafficStats(true);
            e1.printStackTrace();
            return false;
        } catch (IOException e1) {
            NetworkTrafficStats.endTrafficStats(true);
            e1.printStackTrace();
            return false;
        }
        mediaPlayer.start();
        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
            
            @Override
            public void onCompletion(MediaPlayer mp) {
                NetworkTrafficStats.endTrafficStats(true);
                mp.release();
                mp = null;
            }
        });
        return true;
    }
    
    /**
     * use MediaPlayer
     * @param audioFile
     * @return true if play successfully
     */
    private boolean playFromAudioFile(File audioFile) {
        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setDataSource(audioFile.getAbsolutePath());
            mediaPlayer.prepare();
        } catch (IllegalArgumentException e1) {
            e1.printStackTrace();
            return false;
        } catch (IllegalStateException e1) {
            e1.printStackTrace();
            return false;
        } catch (IOException e1) {
            e1.printStackTrace();
            return false;
        }
        mediaPlayer.start();
        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
            
            @Override
            public void onCompletion(MediaPlayer mp) {
                mp.release();
                mp = null;
            }
        });
        return true;
    }

    private Activity getContextActivity() {
        return (null == this.getParent()) ? this : this.getParent();
    }
    
    /**
     * input: Language language, String speakText
     * @author LiuGen
     * @date 2011-5-9
     */
    class AsyncSpeakTask extends AsyncTask<Object, Void, Boolean> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            getContextActivity().setProgressBarIndeterminateVisibility(true);
            Utilities.showShortToast(getContextActivity(), R.string.tts_prepare);
        }
        
        @Override
        protected Boolean doInBackground(Object... params) {
            return speak((Language)params[0], (String)params[1]);
        }
        
        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            getContextActivity().setProgressBarIndeterminateVisibility(false);
            if (!result) {
                Utilities.showShortToast(getContextActivity(), R.string.tts_fail);
            }
        }


        
    }
}
